package org.example.brave.http;

import brave.Request;
import brave.Span;
import brave.internal.Nullable;

/**
 * Abstract request type used for parsing and sampling of http clients and servers.
 *
 * @see HttpClientRequest
 * @see HttpServerRequest
 * @since 5.8
 */
public abstract class HttpRequest extends Request {
    /**
     * The timestamp in epoch microseconds of the beginning of this request or zero to take this
     * implicitly from the current clock. Defaults to zero.
     *
     * <p>This is helpful in two scenarios: late parsing and avoiding redundant timestamp overhead.
     * If a server span, this helps reach the "original" beginning of the request, which is always
     * prior to parsing.
     *
     * <p>Note: Overriding has the same problems as using {@link brave.Span#start(long)}. For
     * example, it can result in negative duration if the clock used is allowed to correct backwards.
     * It can also result in misalignments in the trace, unless {@link brave.Tracing.Builder#clock(Clock)}
     * uses the same implementation.
     *
     * @see HttpResponse#finishTimestamp()
     * @see brave.Span#start(long)
     * @see brave.Tracing#clock(TraceContext)
     * @since 5.8
     */
    public long startTimestamp() {
        return 0L;
    }

    /**
     * The HTTP method, or verb, such as "GET" or "POST".
     *
     * <p>Conventionally associated with the key "http.method"
     *
     * <h3>Note</h3>
     * <p>It is part of the <a href="https://tools.ietf.org/html/rfc7231#section-4.1">HTTP RFC</a>
     * that an HTTP method is case-sensitive. Do not downcase results. If you do, not only will
     * integration tests fail, but you will surprise any consumers who expect compliant results.
     *
     * @see HttpTags#METHOD
     */
    public abstract String method();

    /**
     * The absolute http path, without any query parameters. Ex. "/objects/abcd-ff"
     *
     * <p>Conventionally associated with the key "http.path"
     *
     * <p>{@code null} could mean not applicable to the HTTP method (ex CONNECT).
     *
     * <h3>Implementation notes</h3>
     * Some HTTP client abstractions, such as JAX-RS and spring-web, return the input as opposed to
     * the absolute path. One common problem is a path requested as "", not "/". When that's the case,
     * normalize "" to "/". This ensures values are consistent with wire-level clients and behaviour
     * consistent with RFC 7230 Section 2.7.3.
     *
     * <p>Ex.
     * <pre>{@code
     * @Override public String path() {
     *   String result = delegate.getURI().getPath();
     *   return result != null && result.isEmpty() ? "/" : result;
     * }
     * }</pre>
     *
     * @see #url()
     * @see HttpResponse#route()
     * @see HttpTags#PATH
     */
    @Nullable
    public abstract String path();

    /**
     * Returns an expression such as "/items/:itemId" representing an application endpoint,
     * conventionally associated with the tag key "http.route". If no route matched, "" (empty string)
     * is returned. Null indicates this instrumentation doesn't understand http routes.
     *
     * <p>The route is associated with the request, but it may not be visible until response
     * processing. The reasons is that many server implementations process the request before they can
     * identify the route. Parsing should expect this and look at {@link HttpResponse#route()} as
     * needed.
     *
     * @see HttpRequest#path()
     * @see HttpTags#ROUTE
     * @since 5.10
     */
    @Nullable public String route() {
        return null;
    }

    /**
     * The entire URL, including the scheme, host and query parameters if available or null if
     * unreadable.
     *
     * <p>Conventionally associated with the key "http.url"
     *
     * @see #path()
     * @see HttpResponse#route()
     * @see HttpTags#URL
     */
    @Nullable public abstract String url();

    /** Returns one value corresponding to the specified header, or null. */
    @Nullable public abstract String header(String name);

    HttpRequest() { // sealed type: only client and server
    }
}
